//
//  UIImage+ACExt.m
//  ACFramework
//
//  Created by caoyq on 2018/5/23.
//

#import "UIImage+ACExt.h"
#import <Photos/Photos.h>
#import <Accelerate/Accelerate.h>

@implementation UIImage (ACExt)

+ (UIImage *)localAppIcon
{
    NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary];
    NSString *icon = [[infoPlist valueForKeyPath:@"CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles"] lastObject];
    return [UIImage imageNamed:icon];
}

#pragma mark - 截图

+ (UIImage *)ac_screenShot
{
    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    CGRect rect = [keyWindow bounds];
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [keyWindow.layer renderInContext:context];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    return img;
}

+ (UIImage *)ac_screenShotFromCaptureDevice
{
    CGSize imageSize = CGSizeZero;
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (UIInterfaceOrientationIsPortrait(orientation))
        imageSize = [UIScreen mainScreen].bounds.size;
    else
        imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
    
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    for (UIWindow *window in [[UIApplication sharedApplication] windows])
    {
        CGContextSaveGState(context);
        CGContextTranslateCTM(context, window.center.x, window.center.y);
        CGContextConcatCTM(context, window.transform);
        CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
        if (orientation == UIInterfaceOrientationLandscapeLeft)
        {
            CGContextRotateCTM(context, M_PI_2);
            CGContextTranslateCTM(context, 0, -imageSize.width);
        }
        else if (orientation == UIInterfaceOrientationLandscapeRight)
        {
            CGContextRotateCTM(context, -M_PI_2);
            CGContextTranslateCTM(context, -imageSize.height, 0);
        } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
            CGContextRotateCTM(context, M_PI);
            CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
        }
        if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
        {
            [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
        }
        else
        {
            [window.layer renderInContext:context];
        }
        CGContextRestoreGState(context);
    }
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

+ (UIImage*)ac_imageFromView:(UIView *)view rect:(CGRect)rect
{
    UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 1.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    CGRect myImageRect = rect;
    CGImageRef imageRef = image.CGImage;
    CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef,myImageRect );
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, myImageRect, subImageRef);
    UIImage* smallImage = [UIImage imageWithCGImage:subImageRef];
    CGImageRelease(subImageRef);
    UIGraphicsEndImageContext();
    
    return smallImage;
}

#pragma mark - color

+ (UIImage *)ac_getImageWithColor: (UIColor *)color alpha: (CGFloat)alpha
{
    CGRect frame = CGRectMake(0, 0, 1, 1);
    UIColor *resultColor = [color colorWithAlphaComponent:alpha];
    UIGraphicsBeginImageContext(frame.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [resultColor CGColor]);
    CGContextFillRect(context, frame);
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return theImage;
}

- (UIColor *)ac_colorAtPoint:(CGPoint)point
{
    if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point))
    {
        return nil;
    }
    
    NSInteger pointX = trunc(point.x);
    NSInteger pointY = trunc(point.y);
    CGImageRef cgImage = self.CGImage;
    NSUInteger width = self.size.width;
    NSUInteger height = self.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData,
                                                 1,
                                                 1,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    
    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    CGContextRelease(context);
    
    CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
    CGFloat green = (CGFloat)pixelData[1] / 255.0f;
    CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
    CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

- (UIImage *)ac_convertToGrayImage
{
    int width = self.size.width;
    int height = self.size.height;
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    CGContextRef context = CGBitmapContextCreate(nil,width,height,8,0,colorSpace,kCGImageAlphaNone);
    CGColorSpaceRelease(colorSpace);
    
    if (context == NULL)
    {
        return nil;
    }
    
    CGContextDrawImage(context,CGRectMake(0, 0, width, height), self.CGImage);
    CGImageRef contextRef = CGBitmapContextCreateImage(context);
    UIImage *grayImage = [UIImage imageWithCGImage:contextRef];
    CGContextRelease(context);
    CGImageRelease(contextRef);
    
    return grayImage;
}

#pragma mark - 高斯模糊

- (UIImage *)ac_setBlurImageWithRatio: (CGFloat)ratio
{
    if (ratio < 0.f || ratio > 1.f) {
        ratio = 0.5f;
    }
    
    int boxSize = (int)(ratio * 40);
    boxSize = boxSize - (boxSize % 2) + 1;
    CGImageRef img = self.CGImage;
    vImage_Buffer inBuffer, outBuffer;
    vImage_Error error;
    void *pixelBuffer;
    
    //从CGImage中获取数据
    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
    
    //设置从CGImage获取对象的属性
    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);
    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
    pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");
    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);
    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
    if(error){
        NSLog(@"error from convolution %ld", error);
    }
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate( outBuffer.data, outBuffer.width, outBuffer.height, 8, outBuffer.rowBytes, colorSpace, kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
    
    //clean up CGContextRelease(ctx)
    CGColorSpaceRelease(colorSpace);
    free(pixelBuffer);
    CFRelease(inBitmapData);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(imageRef);
    return returnImage;
}

#pragma mark - 图片切割等操作

- (UIImage *)ac_setRadius: (CGFloat)radius
{
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
    [path addClip];
    [self drawInRect:rect];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

- (UIImage *)ac_getImageInRect: (CGRect)rect
{
    //将UIImage转换成CGImageRef
    CGImageRef sourceImageRef = [self CGImage];
    
    //按照给定的矩形区域进行剪裁
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);
    
    //将CGImageRef转换成UIImage
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    
    //返回剪裁后的图片
    return newImage;
}

- (UIImage *)ac_getImageWithSize: (CGSize)size
{
    
    UIGraphicsBeginImageContext(size);
    
    [self drawInRect:CGRectMake(0,0,size.width,size.height)];
    
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

- (UIImage *)ac_getCircleImage
{
    return [self ac_getCircleImageAllowClip:YES];
}

- (UIImage *)ac_getCircleImageAllowClip: (BOOL)allowClip
{
    if (allowClip) {
        CGFloat radius = MIN(self.size.width, self.size.height);
        CGFloat x = (self.size.width - radius) / 2;
        CGFloat y = (self.size.height - radius) / 2;
        UIImage *img = [self ac_getImageInRect:CGRectMake(x, y, radius, radius)];
        return [img ac_getCircleImageWithSize:img.size backgroundColor:nil lineColor:nil lineWidth:0];
    }
    return [self ac_getCircleImageWithSize:self.size backgroundColor:nil lineColor:nil lineWidth:0];
}

- (UIImage *)ac_getCircleImageWithSize:(CGSize )size backgroundColor:(UIColor *)backgroundColor lineColor:(UIColor *)lineColor lineWidth:(CGFloat)lineWidth
{
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    //1.上下文  ->在内存中开辟一个地址，这和屏幕显示无关
    //参数 1.绘图尺寸  2.是否不透明：NO(透明)/YES（不透明）  3.屏幕的分辨率，默认如果不指定，默认的图像显示1.0的分辨率，图像质量不好，可以指定为0，会选择当前屏幕的分辨率
    BOOL opaque = backgroundColor ? YES : NO;
    UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
    
    //2.绘图 drawInRect就是在指定区域内拉伸屏幕  核心绘图的重点：路径
    //a.背景填充颜色
    if (opaque) {
        [backgroundColor setFill];
        UIRectFill(rect);
    }
    
    //b.实例化一个圆形的路径
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
    
    //c.进行路径裁剪 --后续的绘图，都会在圆形路径内部，外部的全部干掉
    [path addClip];
    
    //d.绘图
    [self drawInRect:rect];
    
    //f.绘制边线
    if (lineColor && lineWidth > 0) {
        [lineColor setStroke];
        path.lineWidth = lineWidth;
        [path stroke];
    }
    
    //3.取得结果
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    //4.关闭上下文
    UIGraphicsEndImageContext();
    
    return image;
}

#pragma mark - 图片旋转与还原

- (UIImage *)ac_rotateWithAngle: (CGFloat)angle
{
    CGSize imgSize = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale);
    CGSize outputSize = imgSize;
    
    UIGraphicsBeginImageContext(outputSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, outputSize.width / 2, outputSize.height / 2);
    CGContextRotateCTM(context, angle * M_PI / 180.0);
    CGContextTranslateCTM(context, -imgSize.width / 2, -imgSize.height / 2);
    [self drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

- (UIImage *)ac_alwaysOrientationUp
{
    if (self.imageOrientation == UIImageOrientationUp) return self;
    CGFloat angle = 0.0f;
    switch (self.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            angle = 180.0f;
            break;
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            angle = 90.0f;
            break;
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            angle = -90.0f;
            break;
        case UIImageOrientationUp:
        case UIImageOrientationUpMirrored:
            break;
    }
    return [self ac_rotateWithAngle:angle];
}

#pragma mark - 图片加logo

- (UIImage *)imageWithLogoText:(NSString *)text
{
    CGFloat contextWidth = self.size.width;
    CGFloat contextHeight = self.size.height + 30;
    //设置上下文（画布）大小
    CGSize size = CGSizeMake(contextWidth, contextHeight);
    //创建一个基于位图的上下文(context)，并将其设置为当前上下文
    UIGraphicsBeginImageContext(size);
    //获取当前上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //画布的高度
    CGContextTranslateCTM(contextRef, 0, self.size.height);
    //画布翻转
    CGContextScaleCTM(contextRef, 1.0, -1.0);
    //在上下文种画当前图片
    CGContextDrawImage(contextRef, CGRectMake(0, 0, self.size.width, self.size.height), [self CGImage]);
    
    CGContextTranslateCTM(contextRef, 0, self.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);
    
    //文字属性
    UIFont *font = [UIFont systemFontOfSize:12];
    NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
    textStyle.lineBreakMode = NSLineBreakByWordWrapping;
    textStyle.alignment = NSTextAlignmentCenter;
    
    CGRect textFrame = CGRectMake(0, self.size.height + 5, contextWidth, 20);
    [text drawInRect:textFrame withAttributes:@{NSFontAttributeName:font, NSParagraphStyleAttributeName:textStyle,NSForegroundColorAttributeName:[UIColor purpleColor]}];
    
    //从当前上下文种获取图片
    UIImage *targetimg = UIGraphicsGetImageFromCurrentImageContext();
    //移除栈顶的基于当前位图的图形上下文。
    UIGraphicsEndImageContext();
    return targetimg;
    
}

@end
